package com.passioneffect.display {
	import flash.display.DisplayObject;
	import flash.display.Graphics;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.utils.Timer;
	
	import com.passioneffect.adapter.ContentMovieClipAdapter;
	import com.passioneffect.collection.Collection;
	import com.passioneffect.collection.Iterator;
	import com.passioneffect.contentmcs.AbstractContentMovieClip;
	import com.passioneffect.events.PEEvent;
	import com.passioneffect.layout.Layout;
	import com.passioneffect.layoutflow.LayoutFlow;
	import com.passioneffect.parser.IXMLParser;
	import com.passioneffect.parser.ValuePairParser;
	import com.passioneffect.scroll.ScrollHandler;
	
	import Boolean;
	import Number;
	import String;
	import String;
	import gs.TweenMax;	

	//import caurina.transitions.Tweener;	

	/**
	 * @author Passion Effect
	 */

	public class Component extends MovieClip {
		protected var _contentClass : String = "ContentMovieClip_MC";
		protected var auto : Boolean = true;

		private var funcs : Array = [];
		private var xmlLoader : URLLoader;
		protected var _compWidth : Number = 0;
		protected var _compHeight : Number = 0;
		private var _selectedItem : ContentMovieClipAdapter;

		//parameters for effects
		public var startUpMotion : Boolean;
		public var autoStart : Boolean = true;

		protected var items : Collection;
		protected var _source : String = "";
		protected var viewList : Collection;
		protected var _layout : Layout;

		private var _lockSelect : Boolean;
		private var _lockInvalidate : Boolean;
		private var _lockScroll : Boolean;
		protected var _lockMouseScroll : Boolean;

		protected var placeFunc : Function;
		protected var _scrollingMouseWheel : Boolean;

		public var scrollTargetItem : ContentMovieClipAdapter;
		public var alignTargetItem : ContentMovieClipAdapter;

		public var _percentAlignX : Number = 0.5;
		public var _percentAlignY : Number = 0.5;

		public var _spacing : Number = 0;
		protected var _inited : Boolean;
		protected var _defaultIndex : int = -1;

		protected var timer : Timer;
		protected var layoutClass : Class;
		protected var layoutFlow : LayoutFlow;
		protected var xmlParser : IXMLParser;
		protected var _type : String;
		protected var _direction : String;

		protected var _transitionTime : Number = 1;

		public var _scrollTime : Number = 0.5;
		public var scrollTransition : String = "easeOut";

		public var unselectedWidth : Number = 100;
		public var unselectedHeight : Number = 100;
		public var autoScrollToSelectedItem : Boolean = true;

		public var autoLockSelection : Boolean = false;
		public var autoMouseScroll : Boolean = true;
		public var mouseScrollSpeed : Number = 50;

		protected var _xml : XML;
		protected var styleXMLParser : IXMLParser;
		private var _styleURL : String = "";
		private var styleXMLLoader : URLLoader;

		private var _style : XML;
		private var styleReady : Boolean;
		private var waitStyle : Boolean;
		private var _over : ContentMovieClipAdapter;
		public var lockScrollWhileSelect : Boolean;
		public var scrollBasedOnUnselected : Boolean = false;

		protected var _mask : Boolean = false;
		protected var mask_mc : Sprite;
		private var _source2 : *;
		protected var scrollFunction : Function;

		public var customSkin : Boolean = true;
		private var atPercent : Number = 0.5;
		private var atItemPercent : Number = 0.5;
		private var _parentComponent : Component;
		
		public function Component(parentComponent : Component = null,auto : Boolean = true) {
			this.auto = auto;
			if(!this.auto)return;
			
			_parentComponent = parentComponent;
			
			_compWidth = this.width;
			_compHeight = this.height;
			scaleX = scaleY = 1;
			
			if(parent) {
				//for drag and drop
				doLater(init);
			}else {
				this.addEventListener(Event.ADDED_TO_STAGE, addToStageHandler);
			}
			
			while(numChildren > 0) {
				removeChildAt(0);
			}
			
			scrollFunction = ScrollHandler.scroll;
			stop();
		}

		protected function addToStageHandler(event : Event) : void {
			init();
		}
		
		

		protected function drawMask() : void {
			if(mask_mc == null) {
				mask_mc = new Sprite();
				addChild(mask_mc);
				this.mask = mask_mc;
			}
			
			var g : Graphics = mask_mc.graphics;
			g.lineStyle();
			g.beginFill(0x000000, 1);
			g.drawRect(0, 0, compWidth, compHeight);
			g.endFill();
		}

		public function getStartX() : Number {
			return layout.getStartX();
		}

		public function getEndX() : Number {
			return layout.getEndX();
		}

		public function getMinX() : Number {
			//override
			return 0;
		}

		public function getMaxX() : Number {
			//override
			return 0;
		}

		public function getMinY() : Number {
			//override
			return 0;
		}

		public function getMaxY() : Number {
			//override
			return 0;
		}

		//trigger when add to stage, not use by composer
		private function addedHandler(event : Event = null) : void {
			setMouseEvents();
		}

		public function setMouseEvents() : void {
			this.addEventListener(Event.ENTER_FRAME, scrollHandler);
		}

		protected function scrollHandler(evt : Event) : void {
			if(!hitTest())return;
			if(lockScroll)return;
			if(lockScrollWhileSelect && getSelectedItem() != null)return;
			
			//trace("handler");
			scrollFunction(this);
			
		}

		public function removeMouseEvents() : void {
			this.removeEventListener(Event.ENTER_FRAME, scrollHandler);
		}

		public function get inited() : Boolean {
			return _inited;
		}

		public function getNearestNextIndex() : int {
			//override
			return 0;
		}

		public function getNearestPreviousIndex() : int {
			return 0;
		}

		public function setAlignTarget(adapter : ContentMovieClipAdapter) : void {
			alignTargetItem = adapter;
		}

		protected function dispatchChangeSetting(attName : String,value : *) : void {
			if(!inited)return;
			var itr : Iterator = items.iterator();
			var item : ContentMovieClipAdapter;
			var mc : MovieClip;
			
			while(itr.hasNext()) {
				item = ContentMovieClipAdapter(itr.next());
				mc = item.getMovieClip();
				mc.changeSetting(attName, value);
			}
		}

		public function get defaultIndex() : int {
			return _defaultIndex;
		}

		private function styleLoaded(event : Event) : void {
			XML.ignoreWhitespace = true;
			var xml : XML = new XML(event.target.data);
			this._style = xml;
			parseStyle(xml);
			dispatchEvent(new PEEvent(PEEvent.STYLE_XML_LOADED));
		}

		private function xmlLoaded(event : Event) : void {
			XML.ignoreWhitespace = true;
			var xml : XML = new XML(event.target.data);
			this._xml = xml;
			parseXML(xml);
			dispatchEvent(new PEEvent(PEEvent.XML_LOADED));
			draw();
		}

		private function validate(evt : Event) : void {
			for each(var func:Function in funcs) {
				func.apply(this);
			}
			funcs = [];
			this.removeEventListener(Event.ENTER_FRAME, validate);
		}

		//public functions
		public function draw() : void {
			layoutItems();
		}

		public function invalidate() : void {
			if(lockInvalidate)return;
			doLater(draw);
		}

		public function init() : void {
			
			//this function not for composer
			if(_inited)return;
			viewList = new Collection();
			items = new Collection();
			
			preset();
			
			if(_mask && compWidth != 0 && compHeight != 0) {
				drawMask();
			}
			
			_inited = true;
			if(_source2 != null) {
				if(_source2 is Collection) {
					addItems(_source2);
				}else {
					loadXML(_source2);
				}
			}else if(_source != null) {
				loadStyleXML(_styleURL);
				loadXML(_source);
			}
			onInitItems();
			if(stage) {
				addedHandler();
			}else {
				addEventListener(Event.ADDED_TO_STAGE, addedHandler);
			}
			_inited = true;
		}

		public function getOverItem() : ContentMovieClipAdapter {
			return _over;
		}

		public function takeOver(component : Component) : void {
			//this is init for composer
			//should be addChild to parent component before call this function.
			startUpMotion = false;
			//setMouseEvents();

			unselectedWidth = component.unselectedSize.width;
			unselectedHeight = component.unselectedSize.height;
			
			_spacing = 0;
			addItems(component.getItems());
			var itr : Iterator = items.iterator();
			while(itr.hasNext()) {
				var item : ContentMovieClipAdapter = ContentMovieClipAdapter(itr.next());
				item.takeOverBy(this);
			}
			
			//this have to after add items;
			if(!isNaN(component.scrollPercentX)) {
				TweenMax.killTweensOf(_layout, false);
				scrollPercentX = component.scrollPercentX;
			}
			
			onInitItems();
			
			_inited = true;
		}

		public function loadStyleXML(url : String) : void {
			if(url == null || url == "")return;
			
			if(styleXMLLoader == null) {
				styleXMLLoader = new URLLoader();
				styleXMLLoader.addEventListener(Event.COMPLETE, styleLoaded);
			}
			
			styleXMLLoader.load(new URLRequest(url));
		}

		public function loadXML(source : *,append : Boolean = false) : void {
			if(!_inited) {
				_source2 = source;
				return;
			}
			
			if(!append)resetData();
			
			if(source is String) {
				if(xmlLoader == null) {
					xmlLoader = new URLLoader();
					xmlLoader.addEventListener(Event.COMPLETE, xmlLoaded);
					xmlLoader.addEventListener(IOErrorEvent.IO_ERROR, xmlLoadError);
					xmlLoader.addEventListener(ProgressEvent.PROGRESS, xmlProgress);
				}
				xmlLoader.load(new URLRequest(source));
			}else if(source is XML) {
				parseXML(source as XML);
			}
		}

		public function addItem(data : Object) : void {
			
			if(!_inited) {
				if(_source2 == null) {
					_source2 = new Collection();
				}
				
				Collection(_source2).addItem(data);
				return;
			}
			
			var adapter : ContentMovieClipAdapter = new ContentMovieClipAdapter();
			adapter.init(items.getLength(), data, this);
			items.addItem(adapter);
		}

		//selection functions

		public function next() : void {
			var index : int = getSelectedIndex() + 1;
			if(index < 0)index = 0;
			else if(index > items.getLength() - 1) {
				index = items.getLength() - 1;
			}
			
			selectAdapter(ContentMovieClipAdapter(items.getItemAt(index)));
		}

		public function previous() : void {
			var index : int = getSelectedIndex() - 1;
			if(index < 0)index = 0;
			else if(index > items.getLength() - 1) {
				index = items.getLength() - 1;
			}
			
			selectAdapter(ContentMovieClipAdapter(items.getItemAt(index)));
		}

		public function selectIndex(index : int) : void {
			var adapter : ContentMovieClipAdapter = ContentMovieClipAdapter(items.getItemAt(index));
			selectAdapter(adapter);
		}

		public function setSize(width : Number,height : Number) : void {
			_compWidth = width;
			_compHeight = height;
			if(_mask) {
				drawMask();
			}
			if(inited) {
				draw();
			}
			dispatchEvent(new PEEvent(PEEvent.RESIZE));
		}

		public function addItems(arr : *) : void {
			if(arr is Array) {
				for each(var item:Object in arr) {
					addItem(item);
				}
			}else if(arr is Collection) {
				var itr : Iterator = arr.iterator();
				while(itr.hasNext()) {
					addItem(itr.next());
				}
			}
		}

		public function selectItemMovieClip(mc : AbstractContentMovieClip,lock : Boolean = false) : Boolean {
			if(lockSelect)return false;
			if(lock)lockSelect = true;
			var adapter : ContentMovieClipAdapter = mc.adapter;
			return selectAdapter(adapter);
		}

		public function getSelectedItem() : ContentMovieClipAdapter {
			return _selectedItem;
		}

		public function getSelectedIndex() : Number {
			if(_selectedItem == null)return -1;
			return _selectedItem.getIndex();
		}

		public function get contentClass() : String {
			return _contentClass;
		}

		public function getLength() : int {
			return items.getLength();
		}

		public function get total() : int {
			return items.getLength();
		}

		public function getTotalLength() : Number {
			return _layout.getTotalLengthX();
		}

		public function updateLayout(adapter : ContentMovieClipAdapter,layoutValue : *) : void {
			//if some item is selected to be scroll target

			if(scrollTargetItem) {
				scrollToIndex(scrollTargetItem.getIndex());
			}
			_layout.setLayoutValue(adapter, layoutValue);
			invalidate();
		}

		public function getLayoutValue(adapter : ContentMovieClipAdapter) : Object {
			return _layout.getLayoutValue(adapter);
		}

		public function getLayoutSize(adapter : ContentMovieClipAdapter) : Object {
			var c : Object = _layout.getLayoutValue(adapter);
			if(c) {
				return c;
			}else {
				return unselectedLayoutValue;
			}
		}

		public function removeLayoutValue(adapter : ContentMovieClipAdapter) : void {
			_layout.removeLayoutValue(adapter);
		}

		public function get scrollPercentX() : Number {
			return _layout.scrollPercentX;
		}

		public function set scrollPercentX(percent : Number) : void {
			scrollTargetItem = null;
			//TweenMax.removeTween(_layout, false);
			_layout.scrollPercentX = percent;
			invalidate();
		}

		public function get scrollValue() : Number {
			return _layout.scrollValueX;
		}

		public function set scrollValue(v : Number) : void {
			scrollTargetItem = null;
			_layout.scrollValueX = v;
			invalidate();
		}

		public function scrollXToPercent(percent : Number,atPercent : Number = NaN) : void {
			if(getScrollingLock()) return;
			if(!layout)return;
			
			scrollTargetItem = null;
			var p : Point = layout.getScrollPercentValue(percent, atPercent);
			
			TweenMax.to(_layout, _scrollTime, {scrollValueX:p.x, onUpdate:invalidate});
		}

		public function scroll(speed : Number,cancelable : Boolean = true) : void {
			if(getScrollingLock() && cancelable)return;
			scrollToLengthX(layout.scrollValueX + speed);
		}

		public function scrollToLength(length : Number) : void {
			if(getScrollingLock()) return;
			scrollTargetItem = null;
			var p : Point = _layout.getScrollLengthValue(length);
			
			TweenMax.to(_layout, _scrollTime, {scrollValueX:p.x, scrollValueY:p.y, onUpdate:invalidate});
		}

		public function get scrollX() : Number {
			return _layout.scrollValueX;
		}

		public function set scrollX(x : Number) : void {
			_layout.scrollValueX = x;
		}

		public function scrollToLengthY(length : Number) : void {
			if(getScrollingLock()) return;
			var p : Point = _layout.getScrollLengthValue(length);
			
			TweenMax.to(_layout, _scrollTime, {scrollValueY:p.y, onUpdate:invalidate});
		}

		public function scrollToLengthX(length : Number) : void {
			if(getScrollingLock()) return;
			var p : Point = _layout.getScrollLengthValue(length);
			scrollTargetItem = null;
			
			TweenMax.to(_layout, _scrollTime, {scrollValueX:p.x, onUpdate:invalidate});
		}

		protected function getScrollingLock() : Boolean {
			return lockScroll || lockInvalidate || _scrollingMouseWheel;
		}

		public function scrollToItem(adapter : ContentMovieClipAdapter) : void {
			if(getScrollingLock()) return;
			scrollTargetItem = adapter;
			scrollToIndex2(adapter.getIndex());
		}
		
		public function resetScroll():void{
			if(scrollTargetItem){
				scrollToIndex2(scrollTargetItem.getIndex());
			}
		}
		
		public function scrollToId(id : String) : void {
			var itr : Iterator = getItems().iterator();
			var item : ContentMovieClipAdapter;
			while(itr.hasNext()) {
				item = ContentMovieClipAdapter(itr.next());
				if(item.id == id) {
					scrollToItem(item);
					return;
				}
			}
		}

		public function scrollToIndex(index : int) : void {
			if(getScrollingLock()) return;
			var adapter : ContentMovieClipAdapter = ContentMovieClipAdapter(items.getItemAt(index));
			scrollTargetItem = adapter;
			
			scrollToIndex2(index);
		}

		public function scrollToIndex2(index : int) : void {
			if(getScrollingLock()) return;
			if(index >= total)index = total - 1;
			else if(index < 0)index = 0;
			
			var p : Point = _layout.getScrollValue(index, atItemPercent, atPercent);
			
			TweenMax.to(layout, _scrollTime, {onComplete:finishScrollItem, onCompleteParams:[index], scrollValueX:p.x, scrollValueY:p.y, onUpdate:invalidate});
			
			dispatchEvent(new PEEvent(PEEvent.SCROLL_TO_ITEM, index, getDataOf(index)));
		}

		public function finishScrollItem(index : int) : void {
			dispatchEvent(new PEEvent(PEEvent.FINISH_SCROLL_TO_ITEM, index, getDataOf(index)));
		}

		
		
		
		public function getDataOf(index : int) : Object {
			var adapter : ContentMovieClipAdapter = ContentMovieClipAdapter(items.getItemAt(index));
			
			if(!adapter)return null;
			return adapter.data; 
		}

		public function skipToIndex(index : int) : void {
			if(getScrollingLock()) return;
			if(index >= total)index = total - 1;
			else if(index < 0)index = 0;
			
			scrollTargetItem = ContentMovieClipAdapter(items.getItemAt(index));
			
			var p : Point = layout.getScrollValue(index, atItemPercent, atPercent);
			TweenMax.to(layout, 0, {scrollValueX:p.x, scrollValueY:p.y, onUpdate:invalidate});
		}

		public function removeItemMovieClip(adapter : ContentMovieClipAdapter) : void {
			items.removeItem(adapter);
			viewList.removeItem(adapter);
			var i : int = 0;
			var itr : Iterator = items.iterator();
			while(itr.hasNext()) {
				ContentMovieClipAdapter(itr.next()).setIndex(i++);
			}
			invalidate();
		}

		public function removeItem(item : Object) : void {
			
			if(!inited) {
				if(_source2) {
					Collection(_source2).removeItem(item);
				}
				return;
			}
			
			if(item is ContentMovieClipAdapter) {
				removeItemMovieClip(item as ContentMovieClipAdapter);
			}else {
				
				var itr : Iterator = items.iterator();
				while(itr.hasNext()) {
					var itm : ContentMovieClipAdapter = ContentMovieClipAdapter(itr.next());
					if(itm.data == item) {
						
						removeItemMovieClip(itm);
						return;
					}
				}
			}
		}

		public function removeAllItems() : void {
			
			items.removeAll();
			viewList.removeAll();
			
			invalidate();
		}

		public function insertItemMovieClip(adapter : ContentMovieClipAdapter,index : int) : void {
			items.addItemAt(adapter, index);
			
			var i : int = index + 1;
			var itr : Iterator = items.iterator(index + 1);
			while(itr.hasNext()) {
				ContentMovieClipAdapter(itr.next()).setIndex(i);
			}
			invalidate();
		}

		protected function parseStyle(xml : XML) : void {
			styleXMLParser = new ValuePairParser();
			
			var style : Array = styleXMLParser.parse(xml);
			
			for(var att:String in style) {
				if(style[att] == "false") {
					this[att] = false;
				}else if(style[att] == "true") {
					this[att] = true;
				}else {
					this[att] = style[att];
				}
			}
			if(waitStyle) {
				onInitItems();
			}
			styleReady = true;
		}

		public function parseXML(_xml : *) : void {
			var xml : XML;
			if(_xml is String) {
				xml = new XML(_xml);
			}else if(_xml is XML) {
				xml = _xml;
			}
			
			
			addItems(xmlParser.parse(xml));
			//todo: when append data, total will have problem 
			if(styleReady || style == "" || style == null) {
				onInitItems();
			}else {
				waitStyle = true;
			}
		}

		protected function postset() : void {
			//override
		}

		protected function onInitItems(defaultPlaceFunc : Function = null) : void {
			
			if(parentComponent == null && _defaultIndex != -1) {
				_selectedItem = ContentMovieClipAdapter(items.getItemAt(_defaultIndex));
			}
			
			_layout.preset();
			postset();
			
			placeFunc = defaultPlaceFunc || placeMC;
			
			
			if(!autoStart)return;
			//first initialize motion function
			if(startUpMotion) {
				placeFunc = initMotionFunc;
				invalidate();
			}
			
			placeFunc = defaultPlaceFunc || placeMC;
			//regular motion function
		}

		protected function initMotionFunc(mc : MovieClip,p : Point,interValue : Object = null) : void {
			if(interValue == null) {
				interValue = {};
			}
			interValue.x = p.x;
			interValue.y = p.y;
			mc.initMotion(interValue);
		}

		protected function placeMotionMC(mc : MovieClip,p : Point,interValue : Object = null) : void {
			if(interValue) {
				mc.onInterValue(interValue);
			}
			
			TweenMax.to(mc, _transitionTime, {x:p.x, y:p.y});
		}

		public function set transitionTime(t : Number) : void {
			_transitionTime = t;
		}

		public function get transitionTime() : Number {
			return _transitionTime;			
		}

		protected function completeChangeMotion() : void {
			
			lockInvalidate = false;
			placeFunc = placeMC;
			setMouseEvents();
		}

		public function changeMotionInvalidate(time : Number = -1) : void {
			removeMouseEvents();
			placeFunc = placeMotionMC;
			//so only can use draw() to force it to layou items.
			lockInvalidate = true;
			//Tweener.removeTweens(_layout);
			//TweenMax.removeTween(_layout, false);
			draw();
			
			if(timer) {
				timer.stop();
				timer.removeEventListener(TimerEvent.TIMER, completeChangeMotionTimer);
				timer = null;
			}
			if(time == 0) {
				completeChangeMotionTimer();
				return;
			}
			
			timer = new Timer(_transitionTime * 1000);
			timer.addEventListener(TimerEvent.TIMER, completeChangeMotionTimer);
			timer.start();
		}

		private function completeChangeMotionTimer(event : TimerEvent = null) : void {
			if(timer) {
				timer.stop();
				timer.removeEventListener(TimerEvent.TIMER, completeChangeMotionTimer);
				
				timer = null;
			}
			
			completeChangeMotion();
		}

		protected function layoutChangePreset(type : String) : void {
			//override
		}

		protected function placeMC(mc : MovieClip,p : Point,interValue : Object = null) : void {
			if(interValue == null) {
				interValue = {};
			}
			interValue.x = p.x;
			interValue.y = p.y;
			mc.onInterValue(interValue);
		}

		public function setOverItem(adapter : ContentMovieClipAdapter) : void {
			_over = adapter;
			dispatchEvent(new PEEvent(PEEvent.MOUSE_OVER_ITEM, adapter.getIndex(), adapter.data));
		}

		public function setOutItem(adapter : ContentMovieClipAdapter) : void {
			if(_over == adapter) {
				_over = null;
				dispatchEvent(new PEEvent(PEEvent.MOUSE_OUT_ITEM, adapter.getIndex(), adapter.data));
			}
		}

		//protected functions
		protected function setLayout(layout : Layout) : void {
			this._layout = layout;
		}

		protected function preset() : void {
			//override for setting default value of each component diff from Component class
		}

		protected function resizeInvalidate() : void {
			//override
		}

		protected function xmlProgress(event : ProgressEvent) : void {
			//override
		}

		public function get unselectedSize() : Rectangle {
			return new Rectangle(0, 0, rootComponent.unselectedWidth, rootComponent.unselectedHeight);
		}

		protected function xmlLoadError(event : IOErrorEvent) : void {
			//override
		}

		protected function resetData() : void {
			//override
		}

		public function clearDoLater() : void {
			funcs = [];
			this.removeEventListener(Event.ENTER_FRAME, validate);
		}

		protected function doLater(func : Function) : void {
			for(var i:String in funcs) {
				if(funcs[i] == func) {
					return;
				}
			}
			funcs.push(func);
			this.addEventListener(Event.ENTER_FRAME, validate);
		}

		protected function layoutItems() : void {
			layoutFlow.layoutFlow(_layout, viewList, items, this, placeFunc);
		}

		protected function selectAdapter(adapter : ContentMovieClipAdapter) : Boolean {
			if(lockSelect)return false;
			
			if(adapter == null || adapter == _selectedItem)return false;
			
			var old : ContentMovieClipAdapter = _selectedItem;
			this._selectedItem = adapter;
			
			if(old != null)onUnselectItem(old);
			onSelectItem(adapter);
			
			return true;
		}

		public function removeFromViewList(adapter : ContentMovieClipAdapter) : void {
			if(viewList.contains(adapter)) {
				viewList.removeItem(adapter);
				adapter.setMovieClip(new MovieClip());
			}
		}

		public function unselect(lock : Boolean = false) : Boolean {
			if(_selectedItem == null || lockSelect)return false;
			var adapter = _selectedItem;
			_selectedItem = null;
			onUnselectItem(adapter);
			
			return true;
		}

		public function get compWidth() : Number {
			return _compWidth;
		}

		public function get compHeight() : Number {
			return _compHeight;
		}

		protected function onUnselectItem(adapter : ContentMovieClipAdapter) : void {
			var mc : MovieClip = adapter.getMovieClip();
			mc.onUnselect();
			dispatchEvent(new Event(Event.CLOSE));
		}

		override public function dispatchEvent(evt : Event) : Boolean {
			if(parentComponent){
				parentComponent.dispatchEvent(evt);
			}
			super.dispatchEvent(evt);
			return true;
		}

		protected function onSelectItem(adapter : ContentMovieClipAdapter) : void {
			var mc : MovieClip = adapter.getMovieClip();
			
			if(autoScrollToSelectedItem) {
				scrollToItem(adapter);
			}
			
			mc.onSelect();
			dispatchEvent(new Event(Event.OPEN));
			dispatchEvent(new PEEvent(PEEvent.CLICK_ITEM, adapter.getIndex(), adapter.data,this));
		}

		public function get __spacing() : Number {
			return _spacing;
		}

		public function set __spacing(v : Number) : void {
			_spacing = v;
			if(_inited) {
				_layout.attValues.spacing = v;
				invalidate();
			}
		}

		[Inspectable(type=String,defaultValue="")]

		public function get source() : String {
			return _source;
		}

		public function set source(url : String) : void {
			_source = url;
			if(_inited)loadXML(url);
		}

		[Inspectable(type=String,defaultValue="")]

		public function get style() : String {
			return _styleURL;
		}

		public function set style(url : String) : void {
			_styleURL = url;
			if(inited)loadStyleXML(url);
		}

		public function get percentAlignX() : Number {
			return _percentAlignX;
		}

		public function set percentAlignX(percentAlignX : Number) : void {
			_percentAlignX = percentAlignX;
			if(_inited) {
				_layout.percentAlign.x = percentAlignX;
			}
		}

		public function get percentAlignY() : Number {
			return _percentAlignY;
		}

		public function set percentAlignY(percentAlignY : Number) : void {
			_percentAlignY = percentAlignY;
			
			if(_inited) {
				_layout.percentAlign.y = percentAlignY;
			}
		}

		public function get direction() : String {
			return _direction;
		}

		public function set direction(t : String) : void {
			if(t == _direction)return;
			_direction = t;
			layoutChangePreset(t);
			dispatchChangeSetting("direction", t);
			changeMotionInvalidate();
		}

		public function getItems() : Collection {
			return items.clone();
		}

		public function get lockInvalidate() : Boolean {
			return _lockInvalidate;
		}

		public function set lockInvalidate(lockInvalidate : Boolean) : void {
			_lockInvalidate = lockInvalidate;
		
			clearDoLater();
		}

		public function get lockScroll() : Boolean {
			return _lockScroll;
		}

		public function set lockScroll(lockScroll : Boolean) : void {
			_lockScroll = lockScroll;
			if(TweenMax.getTweensOf(_layout).length > 0){
				//TweenMax.removeTween(_layout, false);
			}
		}

		public function hitTestRange() : Boolean {
			return layout.hitTest();			
		}

		public function hitTest() : Boolean {
			var rect : Rectangle = new Rectangle(0,0, compWidth, compHeight);
			if(rect.contains(this.mouseX, this.mouseY)) {
				return true;
			}
			return false;
		}

		public function get parentComponent() : Component {
			return _parentComponent;
		}

		
		public function get rootComponent() : Component {
			var comp : Component = this;
			while(comp.parentComponent) {
				comp = comp.parentComponent;
			}
			return comp;
		}

		public function get layout() : Layout {
			return _layout;
		}

		public function set layout(l : Layout) : void {
			_layout = l;
		}

		public function get lockMouseScroll() : Boolean {
			return _lockMouseScroll;
		}

		public function clearScrollingTween() : void {
			//Tweener.removeTweens(layout);
		//	TweenMax.removeTween(layout, false);
		}

		public function set lockMouseScroll(lockMouseScroll : Boolean) : void {
			
			_lockMouseScroll = lockMouseScroll;
			if(lockMouseScroll) {
				removeMouseEvents();
			}else {
				setMouseEvents();
			}
			//TweenMax.removeTween(layout, false);
		}

		public function get unselectedX() : Number {
			if(direction == "horizontal") {
				return unselectedWidth;
			}else {
				return unselectedHeight;
			}
		}

		public function get unselectedY() : Number {
			if(direction == "horizontal") {
				return unselectedHeight;
			}else {
				return unselectedWidth;
			}
		}

		public function get unselectedLayoutValue() : Object {
			return {xLength:unselectedX, yLength:unselectedY, width:unselectedWidth, height:unselectedHeight};
		}

		public function get lockSelect() : Boolean {
			return _lockSelect;
		}

		public function set lockSelect(lockSelect : Boolean) : void {
			_lockSelect = lockSelect;
		}

		public function get compLengthX() : Number {
			if(direction == "horizontal") {
				return compWidth;
			}else {
				return compHeight;
			}
		}

		public function get compLengthY() : Number {
			if(direction == "horizontal") {
				return compHeight;
			}else {
				return compWidth;
			}
		}

		public function get type() : String {
			return _type;
		}

		public function set type(type : String) : void {
			_type = type;
		}
		
		public function set parentComponent(parentComponent : Component) : void {
			_parentComponent = parentComponent;
		}
	}
}
